from sqlalchemy import Column, String, Integer, Text, ForeignKey, Numeric, TIMESTAMP, Boolean, UniqueConstraint, LargeBinary
from sqlalchemy.sql import func
from sqlalchemy.dialects.postgresql import UUID, ENUM as PGEnum
from sqlalchemy.orm import relationship
from app.db.postgres import Base


# PostgreSQL ENUM types (refer to pre-existing types; do not create)
activity_status_enum = PGEnum('draft','ready','in_progress','to_summarize','evaluating','evaluated','archived', name='activity_status', create_type=False)
event_status_enum = PGEnum('new','in_progress','resolved','closed', name='event_status', create_type=False)
approval_result_enum = PGEnum('approved','rejected','pending', name='approval_result', create_type=False)
indicator_category_enum = PGEnum('basic','deduct','veto', name='indicator_category', create_type=False)
evaluation_verdict_enum = PGEnum('qualified','unqualified','veto', name='evaluation_verdict', create_type=False)
evaluation_level_enum = PGEnum('excellent','good','pass','fail', name='evaluation_level', create_type=False)
report_status_enum = PGEnum('draft','reviewed','final', name='report_status', create_type=False)
file_visibility_enum = PGEnum('public','private','restricted', name='file_visibility', create_type=False)


class DictionaryType(Base):
    __tablename__ = 'dictionary_type'
    code = Column(Text, primary_key=True)
    name = Column(Text, nullable=False)
    description = Column(Text)


class DictionaryItem(Base):
    __tablename__ = 'dictionary_item'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    type_code = Column(Text, ForeignKey('dictionary_type.code', ondelete='CASCADE'), nullable=False)
    code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    enabled = Column(Boolean, nullable=False)
    order_index = Column(Integer, nullable=False)
    __table_args__ = (UniqueConstraint('type_code', 'code', name='uq_dictionary_item_type_code_code'),)


class Activity(Base):
    __tablename__ = 'activity'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    name = Column(Text, nullable=False)
    activity_type_id = Column(UUID(as_uuid=True), ForeignKey('dictionary_item.id'), nullable=False)
    time_start = Column(TIMESTAMP(timezone=True))
    time_end = Column(TIMESTAMP(timezone=True))
    location_admin = Column(Text, nullable=False)
    location_detail = Column(Text)
    latitude = Column(Numeric(9, 6))
    longitude = Column(Numeric(9, 6))
    description = Column(Text, nullable=False)
    organizer = Column(Text)
    contact_name = Column(Text)
    contact_phone = Column(Text)
    approver_name = Column(Text)
    approved_at = Column(TIMESTAMP(timezone=True))
    approval_result = Column(approval_result_enum)
    indicator_version_id = Column(UUID(as_uuid=True), ForeignKey('indicator_version.id', ondelete='SET NULL'))
    status = Column(activity_status_enum, nullable=False)
    attachments_ref_id = Column(Text)
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class Event(Base):
    __tablename__ = 'event'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    name = Column(Text, nullable=False)
    occurred_at = Column(TIMESTAMP(timezone=True), nullable=False)
    location_admin = Column(Text)
    location_detail = Column(Text)
    latitude = Column(Numeric(9, 6))
    longitude = Column(Numeric(9, 6))
    event_type_id = Column(UUID(as_uuid=True), ForeignKey('dictionary_item.id'))
    description = Column(Text)
    status = Column(event_status_enum, nullable=False)
    attachments_ref_id = Column(Text)
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class Evaluation(Base):
    __tablename__ = 'evaluation'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    version_no = Column(Integer, nullable=False)
    score_total = Column(Numeric(6, 2), nullable=False)
    verdict = Column(Boolean, nullable=False)
    level = Column(evaluation_level_enum)
    summary = Column(Text)
    report_docx_mongo_id = Column(Text)
    template_version_code = Column(Text)
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('activity_id', 'version_no', name='uq_evaluation_activity_version'),)


class IndicatorVersion(Base):
    __tablename__ = 'indicator_version'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    version_code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    source_doc = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class IndicatorDimension(Base):
    __tablename__ = 'indicator_dimension'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    version_id = Column(UUID(as_uuid=True), ForeignKey('indicator_version.id', ondelete='CASCADE'), nullable=False)
    name = Column(Text, nullable=False)
    order_index = Column(Integer, nullable=False)
    __table_args__ = (UniqueConstraint('version_id', 'name', name='uq_indicator_dimension_version_name'),)


class IndicatorTheme(Base):
    __tablename__ = 'indicator_theme'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    dimension_id = Column(UUID(as_uuid=True), ForeignKey('indicator_dimension.id', ondelete='CASCADE'), nullable=False)
    name = Column(Text, nullable=False)
    order_index = Column(Integer, nullable=False)
    __table_args__ = (UniqueConstraint('dimension_id', 'name', name='uq_indicator_theme_dimension_name'),)


class IndicatorItem(Base):
    __tablename__ = 'indicator_item'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    theme_id = Column(UUID(as_uuid=True), ForeignKey('indicator_theme.id', ondelete='CASCADE'), nullable=False)
    name = Column(Text, nullable=False)
    category = Column(indicator_category_enum, nullable=False)
    weight = Column(Numeric(5, 2))
    deduct_value = Column(Numeric(5, 2))
    veto_flag = Column(Boolean, nullable=False)
    order_index = Column(Integer, nullable=False)
    code = Column(Text, unique=True)
    criteria = Column(Text)
    __table_args__ = (UniqueConstraint('theme_id', 'name', name='uq_indicator_item_theme_name'),)


class IndicatorVersionActivityType(Base):
    __tablename__ = 'indicator_version_activity_type'
    version_id = Column(UUID(as_uuid=True), ForeignKey('indicator_version.id', ondelete='CASCADE'), primary_key=True)
    activity_type_id = Column(UUID(as_uuid=True), ForeignKey('dictionary_item.id', ondelete='CASCADE'), primary_key=True)


class EvaluationItemScore(Base):
    __tablename__ = 'evaluation_item_score'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    evaluation_id = Column(UUID(as_uuid=True), ForeignKey('evaluation.id', ondelete='CASCADE'), nullable=False)
    code = Column(Text, ForeignKey('indicator_item.code', ondelete='CASCADE'), nullable=False)
    score_value = Column(Numeric(6, 2))
    is_veto = Column(Boolean, nullable=False)
    comment = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
    __table_args__ = (UniqueConstraint('evaluation_id', 'code', name='uq_eis_eval_code'),)


# RBAC Models
class UserAccount(Base):
    __tablename__ = 'user_account'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    username = Column(Text, nullable=False)
    password_hash = Column(Text, nullable=False)
    full_name = Column(Text)
    email = Column(Text)
    enabled = Column(Boolean, nullable=False)
    created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())


class Role(Base):
    __tablename__ = 'role'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    description = Column(Text)
    enabled = Column(Boolean, nullable=False)


class Menu(Base):
    __tablename__ = 'menu'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    parent_id = Column(UUID(as_uuid=True), ForeignKey('menu.id', ondelete='SET NULL'))
    name = Column(Text, nullable=False)
    path = Column(Text, nullable=False)
    icon = Column(Text)
    order_index = Column(Integer, nullable=False)
    enabled = Column(Boolean, nullable=False)


class UserRole(Base):
    __tablename__ = 'user_role'
    user_id = Column(UUID(as_uuid=True), ForeignKey('user_account.id', ondelete='CASCADE'), primary_key=True)
    role_id = Column(UUID(as_uuid=True), ForeignKey('role.id', ondelete='CASCADE'), primary_key=True)


class RoleMenu(Base):
    __tablename__ = 'role_menu'
    role_id = Column(UUID(as_uuid=True), ForeignKey('role.id', ondelete='CASCADE'), primary_key=True)
    menu_id = Column(UUID(as_uuid=True), ForeignKey('menu.id', ondelete='CASCADE'), primary_key=True)


class IndicatorCodeCounter(Base):
    __tablename__ = 'indicator_code_counter'
    domain = Column(Text, primary_key=True)
    current_value = Column(Integer, nullable=False)
    base = Column(Integer, nullable=False)
    code_length = Column(Integer, nullable=False)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


# Unified report & template & LLM config
class EvaluationTemplate(Base):
    __tablename__ = 'evaluation_template'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    template_version_code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    indicator_version_id = Column(UUID(as_uuid=True), ForeignKey('indicator_version.id', ondelete='SET NULL'))
    word_template_mongo_id = Column(Text)
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class EvaluationReport(Base):
    __tablename__ = 'evaluation_report'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    template_version_code = Column(Text, nullable=False)
    title = Column(Text, nullable=False)
    status = Column(report_status_enum, nullable=False, server_default='draft')
    mongo_report_id = Column(Text)
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    report_id = Column(UUID(as_uuid=True), ForeignKey('evaluation_report_header.id'))
    version_no = Column(Integer)
    adopted = Column(Boolean, nullable=False, server_default='false')
    parent_version_id = Column(UUID(as_uuid=True), ForeignKey('evaluation_report.id', ondelete='SET NULL'))
    __table_args__ = (
        UniqueConstraint('report_id', 'version_no', name='uq_evaluation_report_version'),
    )


class EvaluationReportActivity(Base):
    __tablename__ = 'evaluation_report_activity'
    report_id = Column(UUID(as_uuid=True), ForeignKey('evaluation_report.id', ondelete='CASCADE'), primary_key=True)
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), primary_key=True)
    role = Column(Text)


class LLMProvider(Base):
    __tablename__ = 'llm_provider'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    base_url = Column(Text)
    auth_type = Column(Text, nullable=False)
    enabled = Column(Boolean, nullable=False, server_default='true')
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class LLMModel(Base):
    __tablename__ = 'llm_model'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    provider_id = Column(UUID(as_uuid=True), ForeignKey('llm_provider.id', ondelete='CASCADE'), nullable=False)
    code = Column(Text, nullable=False)
    display_name = Column(Text, nullable=False)
    context_window = Column(Integer)
    max_output_tokens = Column(Integer)
    default_temperature = Column(Numeric(4, 2))
    endpoint_path = Column(Text)
    extra_headers_json = Column(Text)
    enabled = Column(Boolean, nullable=False, server_default='true')


class LLMSecretVault(Base):
    __tablename__ = 'llm_secret_vault'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    provider_id = Column(UUID(as_uuid=True), ForeignKey('llm_provider.id', ondelete='CASCADE'), nullable=False)
    name = Column(Text, nullable=False)
    cipher_algo = Column(Text, nullable=False)
    cipher_text = Column(LargeBinary, nullable=False)
    iv = Column(LargeBinary)
    auth_tag = Column(LargeBinary)
    key_id = Column(Text, nullable=False)
    rotation_version = Column(Integer, nullable=False, server_default='1')
    enabled = Column(Boolean, nullable=False, server_default='true')
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class EvaluationTemplateSectionModel(Base):
    __tablename__ = 'evaluation_template_section_model'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    template_version_code = Column(Text, nullable=False)
    section_no = Column(Text, nullable=False)
    llm_model_id = Column(UUID(as_uuid=True), ForeignKey('llm_model.id', ondelete='RESTRICT'), nullable=False)
class EvaluationReportHeader(Base):
    __tablename__ = 'evaluation_report_header'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    code = Column(Text, nullable=False)
    name = Column(Text, nullable=False)
    adopted_version_id = Column(UUID(as_uuid=True), ForeignKey('evaluation_report.id', ondelete='RESTRICT'))
    created_by = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_by = Column(Text)
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('code', name='uq_evaluation_report_header_code'),)


class NetworkVolumeObservation(Base):
    __tablename__ = 'network_volume_observation'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    platform = Column(Text, nullable=False)
    metric_type = Column(Text, nullable=False)
    value = Column(Numeric(18, 4), nullable=False)
    unit = Column(Text)
    observed_at = Column(TIMESTAMP(timezone=True))
    source_url = Column(Text)
    source_title = Column(Text)
    author_or_account = Column(Text)
    evidence_id = Column(UUID(as_uuid=True), ForeignKey('network_volume_evidence.id', ondelete='SET NULL'))
    fingerprint_hash = Column(Text, nullable=False)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (
        UniqueConstraint('activity_id', 'platform', 'fingerprint_hash', name='uq_nvo_activity_platform_fp'),
    )


class NetworkVolumeAggregate(Base):
    __tablename__ = 'network_volume_aggregate'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    metric_key = Column(Text, nullable=False)
    value = Column(Numeric(18, 4), nullable=False)
    computed_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    details_json = Column(Text)
    __table_args__ = (
        UniqueConstraint('activity_id', 'metric_key', name='uq_nva_activity_metric'),
    )


class NetworkVolumeEvidence(Base):
    __tablename__ = 'network_volume_evidence'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    type = Column(Text, nullable=False)
    path_or_url = Column(Text, nullable=False)
    captured_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    meta_json = Column(Text)


class ActivityCollectionConfig(Base):
    __tablename__ = 'activity_collection_config'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), nullable=False)
    keywords_json = Column(Text)
    accounts_json = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('activity_id', name='uq_acc_activity'),)


class FileAsset(Base):
    __tablename__ = 'file_asset'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    storage_key = Column(Text, nullable=False, unique=True)
    url = Column(Text, nullable=False)
    original_name = Column(Text, nullable=False)
    ext = Column(Text)
    mime_type = Column(Text, nullable=False)
    size_bytes = Column(Integer, nullable=False)
    checksum_sha256 = Column(Text, nullable=False)
    etag = Column(Text)
    bucket = Column(Text)
    storage_provider = Column(Text, nullable=False)
    visibility = Column(file_visibility_enum, nullable=False)
    owner_id = Column(Text)
    uploader_id = Column(UUID(as_uuid=True), ForeignKey('user_account.id', ondelete='SET NULL'))
    expires_at = Column(TIMESTAMP(timezone=True))
    is_deleted = Column(Boolean, nullable=False)
    deleted_at = Column(TIMESTAMP(timezone=True))
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())


class FileMediaInfo(Base):
    __tablename__ = 'file_media_info'
    file_id = Column(UUID(as_uuid=True), ForeignKey('file_asset.id', ondelete='CASCADE'), primary_key=True)
    width = Column(Integer)
    height = Column(Integer)
    duration_ms = Column(Integer)
    thumbnails_json = Column(Text)
    codec = Column(Text)
    orientation = Column(Text)
    dpi = Column(Integer)


class ActivityFileAsset(Base):
    __tablename__ = 'activity_file_asset'
    activity_id = Column(UUID(as_uuid=True), ForeignKey('activity.id', ondelete='CASCADE'), primary_key=True)
    file_id = Column(UUID(as_uuid=True), ForeignKey('file_asset.id', ondelete='CASCADE'), primary_key=True)
    role = Column(Text)


class EventFileAsset(Base):
    __tablename__ = 'event_file_asset'
    event_id = Column(UUID(as_uuid=True), ForeignKey('event.id', ondelete='CASCADE'), primary_key=True)
    file_id = Column(UUID(as_uuid=True), ForeignKey('file_asset.id', ondelete='CASCADE'), primary_key=True)
    role = Column(Text)


class DailyNews(Base):
    __tablename__ = 'daily_news'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    news_id = Column(Text, nullable=False)
    source_platform = Column(Text, nullable=False)
    title = Column(Text, nullable=False)
    url = Column(Text)
    description = Column(Text)
    extra_info = Column(Text)
    crawl_date = Column(Text)
    rank_position = Column(Integer)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('news_id', 'source_platform', 'crawl_date', name='uq_daily_news_unique'),)


class DailyTopic(Base):
    __tablename__ = 'daily_topics'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    topic_id = Column(Text, nullable=False)
    topic_name = Column(Text, nullable=False)
    topic_description = Column(Text)
    keywords_json = Column(Text)
    extract_date = Column(Text, nullable=False)
    relevance_score = Column(Numeric(6, 2))
    news_count = Column(Integer)
    processing_status = Column(Text)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('topic_id', 'extract_date', name='uq_daily_topics_unique'),)


class TopicNewsRelation(Base):
    __tablename__ = 'topic_news_relation'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    topic_code = Column(Text, nullable=False)
    news_id = Column(Text, nullable=False)
    source_platform = Column(Text, nullable=False)
    crawl_date = Column(Text, nullable=False)
    relation_score = Column(Numeric(6, 2))
    extract_date = Column(Text, nullable=False)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('topic_code', 'news_id', 'extract_date', name='uq_topic_news_unique'),)


class CrawlingTask(Base):
    __tablename__ = 'crawling_tasks'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    task_id = Column(Text, nullable=False)
    topic_code = Column(Text, nullable=False)
    topic_ref_id = Column(UUID(as_uuid=True), ForeignKey('daily_topics.id', ondelete='CASCADE'), nullable=False)
    platform = Column(Text, nullable=False)
    search_keywords_json = Column(Text, nullable=False)
    task_status = Column(Text)
    start_time = Column(TIMESTAMP(timezone=True))
    end_time = Column(TIMESTAMP(timezone=True))
    total_crawled = Column(Integer)
    success_count = Column(Integer)
    error_count = Column(Integer)
    error_message = Column(Text)
    config_params_json = Column(Text)
    scheduled_date = Column(Text, nullable=False)
    created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
    __table_args__ = (UniqueConstraint('task_id', name='uq_crawling_tasks_task_id'),)


class WeiboNote(Base):
    __tablename__ = 'weibo_note'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    user_id = Column(Text)
    nickname = Column(Text)
    avatar = Column(Text)
    gender = Column(Text)
    profile_url = Column(Text)
    ip_location = Column(Text)
    note_id = Column(Numeric(20, 0))
    content = Column(Text)
    create_time = Column(Numeric(20, 0))
    create_date_time = Column(Text)
    liked_count = Column(Text)
    comments_count = Column(Text)
    shared_count = Column(Text)
    note_url = Column(Text)
    source_keyword = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('note_id', name='uq_weibo_note_id'),)


class XhsNote(Base):
    __tablename__ = 'xhs_note'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    user_id = Column(Text)
    nickname = Column(Text)
    avatar = Column(Text)
    ip_location = Column(Text)
    note_id = Column(Text)
    type = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    video_url = Column(Text)
    time = Column(Numeric(20, 0))
    last_update_time = Column(Numeric(20, 0))
    liked_count = Column(Text)
    collected_count = Column(Text)
    comment_count = Column(Text)
    share_count = Column(Text)
    image_list = Column(Text)
    tag_list = Column(Text)
    note_url = Column(Text)
    source_keyword = Column(Text)
    xsec_token = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('note_id', name='uq_xhs_note_id'),)


class DouyinAweme(Base):
    __tablename__ = 'douyin_aweme'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    user_id = Column(Text)
    sec_uid = Column(Text)
    short_user_id = Column(Text)
    user_unique_id = Column(Text)
    nickname = Column(Text)
    avatar = Column(Text)
    user_signature = Column(Text)
    ip_location = Column(Text)
    aweme_id = Column(Numeric(20, 0))
    aweme_type = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    create_time = Column(Numeric(20, 0))
    liked_count = Column(Text)
    comment_count = Column(Text)
    share_count = Column(Text)
    collected_count = Column(Text)
    aweme_url = Column(Text)
    cover_url = Column(Text)
    video_download_url = Column(Text)
    music_download_url = Column(Text)
    note_download_url = Column(Text)
    source_keyword = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('aweme_id', name='uq_douyin_aweme_id'),)


class KuaishouVideo(Base):
    __tablename__ = 'kuaishou_video'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    user_id = Column(Text)
    nickname = Column(Text)
    avatar = Column(Text)
    video_id = Column(Text)
    video_type = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    create_time = Column(Numeric(20, 0))
    liked_count = Column(Text)
    viewd_count = Column(Text)
    video_url = Column(Text)
    video_cover_url = Column(Text)
    video_play_url = Column(Text)
    source_keyword = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('video_id', name='uq_kuaishou_video_id'),)


class BilibiliVideo(Base):
    __tablename__ = 'bilibili_video'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    video_id = Column(Numeric(20, 0))
    video_url = Column(Text)
    user_id = Column(Numeric(20, 0))
    nickname = Column(Text)
    avatar = Column(Text)
    liked_count = Column(Integer)
    add_ts = Column(Numeric(20, 0))
    last_modify_ts = Column(Numeric(20, 0))
    video_type = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    create_time = Column(Numeric(20, 0))
    disliked_count = Column(Text)
    video_play_count = Column(Text)
    video_favorite_count = Column(Text)
    video_share_count = Column(Text)
    video_coin_count = Column(Text)
    video_danmaku = Column(Text)
    video_comment = Column(Text)
    video_cover_url = Column(Text)
    source_keyword = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('video_id', name='uq_bilibili_video_id'),)


class TiebaNote(Base):
    __tablename__ = 'tieba_note'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    note_id = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    note_url = Column(Text)
    publish_time = Column(Text)
    user_link = Column(Text)
    user_nickname = Column(Text)
    user_avatar = Column(Text)
    tieba_id = Column(Text)
    tieba_name = Column(Text)
    tieba_link = Column(Text)
    total_replay_num = Column(Integer)
    total_replay_page = Column(Integer)
    ip_location = Column(Text)
    source_keyword = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('note_id', name='uq_tieba_note_id'),)


class ZhihuContent(Base):
    __tablename__ = 'zhihu_content'
    id = Column(UUID(as_uuid=True), primary_key=True, server_default=func.uuid_generate_v4())
    content_id = Column(Text)
    content_type = Column(Text)
    content_text = Column(Text)
    content_url = Column(Text)
    question_id = Column(Text)
    title = Column(Text)
    desc = Column('description', Text)
    created_time = Column(Text)
    updated_time = Column(Text)
    voteup_count = Column(Integer)
    comment_count = Column(Integer)
    source_keyword = Column(Text)
    user_id = Column(Text)
    user_link = Column(Text)
    user_nickname = Column(Text)
    user_avatar = Column(Text)
    user_url_token = Column(Text)
    topic_code = Column(Text)
    task_code = Column(Text)
    published_at = Column(TIMESTAMP(timezone=True))
    __table_args__ = (UniqueConstraint('content_id', name='uq_zhihu_content_id'),)
